home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oh!X 2000 Spring
/
Oh!X 2000 Spring Special CD-ROM (Japan) (Part 1).7z
/
Oh!X 2000 Spring Special CD-ROM (Japan) (Part 1).bin
/
F2JW
/
trans
/
verb.cpp
< prev
Wrap
C/C++ Source or Header
|
2000-01-18
|
63KB
|
2,173 lines
//
// フランス語 → 日本語 翻訳プログラム
//
// 主に動詞に関わるところ
#include "stdafx.h"
#include <ctype.h>
#include "f2j.h"
#include "score.h"
#include "myprot.h"
extern TOKEN *currentTree;
extern ADVERB dic_adverb_NE;
extern PRONOUN dic_indicationg_noun;
extern PRONOUN nullPronoun;
extern BOOL isChanged;
//
// 補語人称代名詞を処理
//
void
ProcessObjectPronoun(TOKEN *start)
{
TOKEN *p = start->next;
if(p == NULL) return;
// le voila
if(p->frPart == FR_PART_ARTICLE_PRONOUN
&& p->next
&& (p->next->frPart & FR_PART_VERB)
&& ((VERB *)p->next->what)->frVerbKind == 0
&& currentTree->punctuation != FR_PUNCT_QUESTION) {
TOKEN *o2 = p, *v = p->next;
SetVerbPronounObject(start, v, v, o2, NULL, NULL, NULL);
if(isChanged) return;
}
if(currentTree->punctuation == FR_PUNCT_QUESTION
|| p->what == &dic_adverb_NE) { // 否定命令文
ProcessObjectPronoun_Normal(start);
} else if((p->frPart & FR_PART_VERB)
&& !(p->frTense & (FR_TENSE)(FR_TENSE_P_PAST | FR_TENSE_P_PRESENT))) {
// 分詞構文では、命令文でないが、動詞が先頭に来る
ProcessObjectPronoun_Order(start);
// 動詞目的語を伴う命令形? eg) allez vous laver les mains.
if(isChanged == FALSE)
ProcessObjectPronoun_Normal(start->next);
} else {
// 最初の1語は飛ばす vous vous levez -> levez-vous-vous とならないように
ProcessObjectPronoun_Normal(start);
}
}
void
ProcessObjectPronoun_Normal(TOKEN *start)
{
TOKEN *prev = start;
TOKEN *p = prev->next;
while(p && p->next) {
TOKEN *verb = p->next;
if((verb->frPart & FR_PART_VERB)
&& verb->which == NULL
&& verb->moved < 2) {
if(p->frPart == FR_PART_SPECIAL_EN)
SwapPronounVerb(start, p, verb);
else if(p->frPart == FR_PART_SPECIAL_SE)
SwapPronounVerb(start, p, verb);
else if(p->frPart == FR_PART_ADVERB_Y)
SwapPronounVerb(start, p, verb);
else if(p->frPart == FR_PART_ARTICLE_PRONOUN) // le, la, les
SwapPronounVerb(start, p, verb);
else if(IsObjectMatch(p, FR_PART_NOUN_OBJECT_BOTH)) {
if(IsObjectMatch(p, FR_PART_NOUN_SUBJECT)) // nous か vous
DeterminNousVous(prev, p, verb);
if(IsObjectMatch(p, FR_PART_NOUN_OBJECT_BOTH)) // DeterminNousVousで、FR_PART_NOUN_SUBJECTにされているかもしれないので、
SwapPronounVerb(start, p, verb);
}
}
prev = p;
p = p->next;
}
}
//
// <Nous>と<Vous>を見極める (主語か目的代名詞か)
//
void
DeterminNousVous(TOKEN *prev, TOKEN *p, TOKEN *verb)
{
if(prev->frPart == FR_PART_NONE // 行頭
|| IsObjectMatch(prev, FR_PART_SENTENCE_ALL) // si vous voulez -> si voulez-vousとならないように
|| prev->frPart == FR_PART_RELATIVE_OBJECT) { // la montre que <vous> achetez.
if((verb->frTense & FR_TENSE_ORIGIN) // Vous avoir rencontr{ est plasir.
|| (verb->frTense & FR_TENSE_P_PRESENT) // Vous <voyant> agir ainsi, elle sera f[ch{e.
|| (verb->punctuation == FR_PUNCT_HYPHEN)) // <Vous> levez-vous?
goto TwoChoice;
p->frPart = FR_PART_NOUN_SUBJECT;
return;
} else if(prev->frPart == FR_PART_NOUN_SUBJECT
|| prev->frPart == FR_PART_RELATIVE_SUBJECT
// || IsObjectMatch(prev, FR_PART_NOUN_GENERAL)
// || IsObjectMatch(prev, FR_PART_NOUN_OBJECT_BOTH)
|| p->frPart == FR_PART_ARTICLE_PRONOUN // le, la, les
|| p->frPart == FR_PART_ADVERB_Y
|| p->what == &dic_adverb_NE) {
p->frPart = FR_PART_NOUN_OBJECT_BOTH;
return;
}
TwoChoice:
TOKEN *altP = CopyCurrentTree(p, "DeterminNousVous");
p->frPart = FR_PART_NOUN_OBJECT_BOTH;
altP->frPart = FR_PART_NOUN_SUBJECT;
}
//
// 補語人称代名詞と動詞を代える
//
void
SwapPronounVerb(TOKEN *start, TOKEN *p, TOKEN *verb)
{
BOOL noChoice = FALSE; // 必ず補語人称代名詞か? (vous, nous)
if(p->moved > 0) return; // すでに移動済み
// DisconnectTOKEN(start, p);
if((verb->punctuation & FR_PUNCT_HYPHEN)
&& verb->next
&& IsObjectMatch(verb->next, FR_PART_NOUN_SUBJECT)) { // 疑問文など vous levez-vous?
// SwapVerbSubject(verb, verb->next);
MustBeSubject(verb->next);
verb = verb->next;
verb->jpProp |= JP_PROP_QUESTION;
}
if(IsTokenFrench(verb, "]tre")) {
TOKEN *nextVerb = verb->next;
while(nextVerb && (nextVerb->frPart & FR_PART_ADVERB)) // Elles se sont <souvent> {crite.
nextVerb = nextVerb->next;
if( nextVerb
&& (nextVerb->frPart & FR_PART_VERB)
&& (nextVerb->frTense == FR_TENSE_PASSIVE)) {
// Je me suis lev{. -> 受動態の候補 eg) etre lev{
// <je suis me> + <lev{> の分詞構文ではない
nextVerb->frPartChoice = (FR_PART)(nextVerb->frPartChoice & ~FR_PART_INDEPENDENCE);
// 複合過去はすでに処理されている
verb->moved++;
verb = nextVerb; // 視点を受動態の動詞に移す eg) il vous est donn{.
}
}
if(p->frPart == FR_PART_SPECIAL_EN) { // il y en a deux -> il a y <en deux>.のために最初に行う
ChangeToObjectPronoun(p, "en");
p->frPart = FR_PART_NOUN_OBJECT_D; // (FR_PART)(FR_PART_NOUN_OBJECT_D | FR_PART_NOUN_OBJECT_I);
} else if(p->frPart == FR_PART_SPECIAL_SE) {
ChangeToPronoun(p, "se");
} else if(p->frPart == FR_PART_ARTICLE_PRONOUN) {
ChangeToObjectPronoun(p, GetTokenFrench(p));
}
if(IsAttribMatch(verb, p)) {
p->frPart = (FR_PART)(p->frPart | FR_PART_NOUN_RECURSIVE);
}
InsertObjectPronounAfterVerb(start, verb, p);
}
//
// 動詞の後に人称格代名詞を入れる
//
void
InsertObjectPronounAfterVerb(TOKEN *start, TOKEN *verb, TOKEN *p)
{
char word[10];
FR_PART frPart;
TOKEN *q;
strcpy(word, GetTokenFrench(p));
DisconnectTOKEN(start, p);
p->moved = TRUE; // 処理済み
if(IsTokenFrench(p, "en")) {
frPart = (FR_PART)(FR_PART_ADJECTIVE | FR_PART_NOUN);
} else {
frPart = FR_PART_NONE;
}
for(q = verb; q && frPart; q = q->next) {
if(q->frPart & frPart) {
frPart = (FR_PART)(frPart & ~q->frPart);
TOKEN *altQ = CopyCurrentTree(q, "InsertObjectPronounAfterVerb");
TOKEN *pronoun = PutNullNoun(FR_PART_NOUN_DEMONSTRATIVE, PRT_CONTROL_ENABLE);
InsertObjectPronoun(altQ, pronoun, word);
}
}
InsertTOKEN(verb, p);
}
void
InsertObjectPronoun(TOKEN *prev, TOKEN *p, char *french)
{
if(!strcmp(french, "y")) {
} else if(!strcmp(french, "en")) {
ChangeToObjectPronoun(p, "en");
if(IsObjectMatch(prev, FR_PART_VERB) == FALSE) {
ChangeProperObject(p, FR_PART_PREPOSIT_DE, JP_PROP_ALL);
p->frPartParent = prev->frPart;
}
} else {
ChangeToObjectPronoun(p, french);
}
InsertTOKEN(prev, p);
}
//
// pretez-le-moi. -> preler + <me> + <le>
// 補語人称代名詞を処理(肯定命令文のみ)
//
void
ProcessObjectPronoun_Order(TOKEN *start)
{
TOKEN *p = start->next;
TOKEN *verb = NULL;
TOKEN *o1 = NULL, *o2 = NULL, *o3 = NULL;
TOKEN *markO1 = NULL, *markO2 = NULL, *markO3 = NULL;
TOKEN *en = NULL, *y = NULL;
if(p == NULL
|| (p->frPart & FR_PART_VERB) == FR_PART_NONE
|| p->which
|| (p->frTense & FR_TENSE_ORDER) == FR_TENSE_NONE
|| p->next == NULL
|| p->punctuation != FR_PUNCT_HYPHEN)
return;
verb = p;
p = p->next;
if( p->moved == FALSE
&& IsObjectMatch(p, FR_PART_ARTICLE_PRONOUN)) {
o2 = p; // le, la, l', les
if(p->punctuation != FR_PUNCT_HYPHEN) goto WrapUp;
p = p->next;
if(p == NULL) return;
}
if( p->moved == FALSE
&& (p->frAttrib & (FR_ATTRIB)(FR_ATTRIB_LEVEL1 | FR_ATTRIB_LEVEL2))) {
if(((p->frAttrib & FR_ATTRIB_PLURAL) && IsObjectMatch(p, FR_PART_NOUN_OBJECT_I))
|| ((p->frAttrib & FR_ATTRIB_SINGLE) && IsObjectMatch(p, FR_PART_NOUN_PERSONAL))) {
o1 = p; // me, te, nous, vous
if(p->punctuation != FR_PUNCT_HYPHEN) goto WrapUp;
p = p->next;
if(p == NULL) return;
}
}
if( p->moved == FALSE
&& (p->frAttrib & FR_ATTRIB_LEVEL3)
&& IsObjectMatch(p, FR_PART_NOUN_OBJECT_I)) {
// 一つの動詞に目的語は2つまで
if(o1 && o2) { markO1 = o1; o1 = NULL; }
o3 = p; // me, te, nous, vous
if(p->punctuation != FR_PUNCT_HYPHEN) goto WrapUp;
p = p->next;
if(p == NULL) return;
}
if(p->frPart == FR_PART_ADVERB_Y) {
// 一つの動詞に目的語は2つまで
if(o2 && o3) { markO2 = o2; o2 = NULL; }
y = p;
if(p->punctuation != FR_PUNCT_HYPHEN) goto WrapUp;
p = p->next;
if(p == NULL) return;
}
if(p->frPart == FR_PART_SPECIAL_EN) {
// 一つの動詞に目的語は2つまで
if(o3 && y) { markO3 = o3; o3 = NULL; }
en = p;
if(p->punctuation != FR_PUNCT_HYPHEN) goto WrapUp;
p = p->next;
if(p == NULL) return;
}
WrapUp:
if(o3) o1 = o3; // lui, leurは間接目的語
// 主語がないので、<attrib>は<verb>で調べる
if(o1 || o2 || y || en)
SetVerbPronounObject(start, verb, verb, o2, o1, y, en);
if(markO1) markO1->moved = TRUE;
if(markO2) markO2->moved = TRUE;
if(markO3) markO3->moved = TRUE;
}
//
// 補語人称代名詞を動詞の目的語として認識する
//
void
SetVerbPronounObject(TOKEN *start, TOKEN *s, TOKEN *v,
TOKEN *o1, TOKEN *o2, TOKEN *y, TOKEN *en)
{
// 何らかの理由で以前に却下されている
if(v->moved) return;
if(en) { // il y en a deux -> il a y <en deux>.のために最初に行う
DisconnectTOKEN(start, en);
InsertTOKEN(v, en);
ChangeToObjectPronoun(en, "en");
en->frPart = FR_PART_NOUN_OBJECT_D; // (FR_PART)(FR_PART_NOUN_OBJECT_D | FR_PART_NOUN_OBJECT_I);
en->moved = TRUE; // 処理済み
}
if(o2) {
if(IsObjectMatch(o2, FR_PART_NOUN_RECURSIVE)); // "se"は判断するまでもない
else if(o2->frAttrib & FR_ATTRIB_LEVEL3)
o2->frPart = FR_PART_NOUN_OBJECT_I; // lui, leur
else
o2->frPart = FR_PART_NOUN_OBJECT_BOTH; // me, te, nous, vous
if(s && IsAttribMatch(o2, s)) { // 主語と同じ<attrib>なら再帰代名詞の可能性もある
o2->frPart = (FR_PART)(o2->frPart | FR_PART_NOUN_RECURSIVE);
o2->frAttrib = (FR_ATTRIB)(s->frAttrib & o2->frAttrib);
}
DisconnectTOKEN(start, o2);
InsertTOKEN(v, o2);
o2->moved = TRUE; // 処理済み
}
if(o1) {
if(o1->frPart == FR_PART_SPECIAL_SE) {
ChangeToPronoun(o1, "se");
} else {
if(s && IsAttribMatch(o1, s)) { // 主語と同じ<attrib>なら再帰代名詞の可能性もある
o1->frPart = (FR_PART)(o1->frPart | FR_PART_NOUN_RECURSIVE);
o1->frAttrib = (FR_ATTRIB)(s->frAttrib & o1->frAttrib);
}
ChangeToObjectPronoun(o1, GetTokenFrench(o1));
}
DisconnectTOKEN(start, o1);
InsertTOKEN(v, o1);
o1->moved = TRUE; // 処理済み
}
if(y) {
DisconnectTOKEN(start, y);
InsertTOKEN(v, y);
y->moved = TRUE; // 処理済み
}
if(o1 || o2 || y || en) { // 受動態の可能性を消す
TOKEN *p = s;
while(p) {
if(p->frPart & FR_PART_VERB)
p->frTense = (FR_TENSE)(p->frTense & ~FR_TENSE_PASSIVE);
if(p == v) break;
p = p->next;
}
}
// この動詞は処理済み
v->moved = TRUE;
}
//
// 名詞 + 動詞句 → 文章
//
void
CombineSubjectVerb(TOKEN *start)
{
TOKEN *p;
TOKEN *subject = NULL, *verb = NULL;
for(p = start; p; p = p->next) {
TOKEN *next = p->next;
if(IsObjectMatch(p, FR_PART_NOUN_ALL)
&& CanBeSubject(p)
&& next
&& (next->frPart & FR_PART_VERB)
&& !(next->frPart & FR_PART_COMBINE)
&& next->subject == NULL
&& !(next->frTense & (FR_TENSE)(FR_TENSE_P_PAST | FR_TENSE_P_PRESENT))
&& (p->what == &nullPronoun || !(next->frTense & FR_TENSE_ORIGIN))
&& next->which) {
subject = p;
verb = p->next;
}
if(ToWaitSubjectVerb(p, subject, verb)) {
subject = verb = NULL;
}
}
if(subject == NULL) return;
// 命令形で主語付き文章は作れない
if(verb->frTense == FR_TENSE_ORDER) {
currentTree->prtControl = PRT_CONTROL_DISABLE;
return;
}
CombineSubjectVerb(start, subject, verb);
if(verb->which) { // 破棄されていなければ
verb->scoreCombine += SCORE_MAKE_SENTENCE;
}
}
BOOL
ToWaitSubjectVerb(TOKEN *p, TOKEN *subject, TOKEN *verb)
{
if(verb
&& (p->frPart & FR_PART_PREPOSIT)
&& p->frPartParent == FR_PART_VERB
&& MatchParentPreposition(verb, p))
return(TRUE);
if(p->frPart == FR_PART_COMBINE_NOUN
// || p->frPart == FR_PART_COMBINE_VERB
|| p->frPart == FR_PART_COMBINE_ADJECTIVE) {
if(p->object1 == NULL)
// && p->object2 == NULL)
return(TRUE);
}
// Est-ce que S + V
if(p->frPart == FR_PART_SPECIAL_ESTCEQUE) {
return(TRUE);
}
return(FALSE);
}
void
CombineSubjectVerb(TOKEN *start, TOKEN *subject, TOKEN *verb)
{
TOKEN *prev = PreviousToken(start, subject, 1);
// le b[timent @ c`t{ duquele je vois (un clocher est l'h`tel).
// -> le b[timent @ c`t{ (duquele je vois un clocher) est l'h`tel.
if(IsObjectMatch(prev, FR_PART_VERB_UNCLEAR)) {
TOKEN *altP = CopyCurrentTree(subject, "SubjectVerb 1");
altP->frPartParent = FR_PART_NONE;
altP->frPartChoice = FR_PART_OBJECT;
} else if(IsObjectMatch(prev, FR_PART_PREPOSIT_UNCLEAR)) {
TOKEN *altP = CopyCurrentTree(subject, "SubjectVerb 2");
altP->frPartParent = FR_PART_PREPOSIT;
altP->frPartChoice = FR_PART_NONE;
}
// 命令形ではない
if(IsTokenFrench(subject, "命令文") == FALSE)
CancelTenseOrder(verb);
DisconnectTOKEN(start, subject);
verb->subject = subject;
verb->synSubject = TRUE;
verb->frPart = (FR_PART)(verb->frPart | FR_PART_SENTENCE_NORMAL);
// j'y vais aussi. <aussi>は、<je>にかかっている
subject->jpEmphasis |= verb->jpEmphasis;
ImproveSubjectVerb(subject, verb);
}
void
CancelTenseOrder(TOKEN *p)
{
if(p == NULL) return;
if(p->frPart & FR_PART_COMBINE) {
if(p->object1) CancelTenseOrder(p->object1);
if(p->object2) CancelTenseOrder(p->object2);
}
p->frTense = (FR_TENSE)(p->frTense & ~FR_TENSE_ORDER);
}
void
ImproveSubjectVerb(TOKEN *subject, TOKEN *verb)
{
if(subject == NULL
|| verb == NULL)
return;
if(verb->frPart & FR_PART_COMBINE) {
if(verb->object1) ImproveSubjectVerb(subject, verb->object1);
if(verb->object2) ImproveSubjectVerb(subject, verb->object2);
return;
}
// Vous allez chanter. の<vous>と<chanter>の組み合わせは行わない。
if(subject->frAttrib
&& verb->frAttrib) {
// 動詞は何種類か候補が或場合が有るので、ここて判定 (je aime, il aimeなど)
FR_ATTRIB frAttrib = (FR_ATTRIB)(subject->frAttrib & verb->frAttrib);
subject->frAttrib = frAttrib;
verb->frAttrib = frAttrib;
}
// 再帰代名詞を間違って選択しないように
if(verb->object1
&& verb->object1->frAttrib != (FR_ATTRIB)(FR_ATTRIB_IL | FR_ATTRIB_ILS) // "se"は無条件で通す
&& IsObjectMatch(verb->object1, FR_PART_NOUN_RECURSIVE)
&& IsAttribMatch(verb->object1, subject) == FALSE) {
verb->object1->frPart = (FR_PART)(verb->object1->frPart & ~(FR_PART_NOUN_RECURSIVE & ~FR_PART_ALL));
}
if(verb->object2
&& verb->object2->frAttrib != (FR_ATTRIB)(FR_ATTRIB_IL | FR_ATTRIB_ILS) // "se"は無条件で通す
&& IsObjectMatch(verb->object2, FR_PART_NOUN_RECURSIVE)
&& IsAttribMatch(verb->object2, verb) == FALSE) {
verb->object2->frPart = (FR_PART)(verb->object2->frPart & ~(FR_PART_NOUN_RECURSIVE & ~FR_PART_ALL));
}
if(subject->frPart & FR_PART_INTERROGATIVE)
subject->jpEmphasis = JP_EMPHASIS_GA;
ReconsiderRecursiveObject(subject, verb);
// 適当な日本語の動詞を選ぶ(その2)
// (今回は構文を変えずに、主語のpropを考慮し、日本語を選び直す)
// 再帰代名詞なども考慮する
SelectJpVerb2(subject, verb);
if(verb == NULL
|| verb->which == NULL)
return;
JP_VERB *jpVerb = (JP_VERB*)verb->which;
TOKEN *obj1 = verb->object1, *obj2 = verb->object2;
// "il"は、NOUN_SUBJECTかNOUN_IMPERSONALかはっきりさせる
if(jpVerb->frPart0 == FR_PART_NOUN_IMPERSONAL)
subject->frPart = FR_PART_NOUN_IMPERSONAL;
ProcessJpHint(subject, verb);
// sentence->scoreCombine += SCORE_MAKE_SENTENCE;
verb->jpUnit = subject->jpUnit; // nous sommes le treize.用
if(obj1 && !(jpVerb->jpHint & JP_HINT_SVA)) {
// TOKEN *obj1 = verb->object1;
if(obj1->object1 && IsObjectMatch(obj1, FR_PART_PREPOSIT_ALL))
obj1 = obj1->object1;
if(IsObjectMatch(obj1, FR_PART_NOUN_ALL))
SelectJpNoun(verb, obj1, verb, jpVerb->jpProp1);
if(IsObjectMatch(obj1, FR_PART_ADJECTIVE_GENERAL)) // Paul est grand. ポールは偉大だ -> 大きい
PrioritizeBehindAdjective(obj1, subject, jpVerb->jpProp1);
else if(IsObjectMatch(obj1, FR_PART_VERB_INF))
ImproveSubjectVerb(subject, obj1);
}
if(obj2) {
if(obj2->object1 && IsObjectMatch(obj2, FR_PART_PREPOSIT_ALL))
obj2 = obj2->object1;
if(IsObjectMatch(obj2, FR_PART_NOUN_ALL))
SelectJpNoun(verb, obj2, verb, jpVerb->jpProp2);
if(IsObjectMatch(obj2, FR_PART_ADJECTIVE_GENERAL)) // Paul est grand. ポールは偉大だ -> 大きい
PrioritizeBehindAdjective(obj2, subject, jpVerb->jpProp1);
else if(IsObjectMatch(obj2, FR_PART_VERB_ALL)) {
if(jpVerb->jpHint & JP_HINT_SVOV)
ImproveSubjectVerb(obj1, obj2);
else
ImproveSubjectVerb(subject, obj2);
}
}
if((jpVerb->jpHint & JP_HINT_PUTTOGETHER12)
&& obj1
&& obj2) {
SelectJpNoun(verb, obj1, verb, obj2->jpProp, jpVerb->jpProp1);
SelectJpNoun(verb, obj2, verb, obj1->jpProp, jpVerb->jpProp2);
SelectJpNoun(verb, obj1, verb, obj2->jpProp, jpVerb->jpProp1);
}
if((jpVerb->jpHint & JP_HINT_SVOA)
&& obj1
&& obj2) {
if(obj2->frPart & FR_PART_ADJECTIVE) {
if(IsObjectMatch(obj2, FR_PART_ADJECTIVE_GENERAL)
&& !(obj2->frPart & FR_PART_COMBINE)) {
// FR_PART_ADJECTIVE_GENERAL_B / GENERAL_F を取り消す
obj2->frPart = FR_PART_ADJECTIVE_GENERAL;
}
SelectJpAdjective2(obj1, obj2, verb, FR_LOCATION_BOTH);
} else if(obj2->frPart & FR_PART_ADVERB) {
SelectJpAdverb2(obj1, obj2, verb);
}
}
if(jpVerb->Exec) jpVerb->Exec(verb);
}
//
// 動詞の目的語の再帰代名詞をチェック
// eg.) allez vous laver les mains.
BOOL
ReconsiderRecursiveObject(TOKEN *subject, TOKEN *verb)
{
BOOL hit = FALSE;
// 主語・動詞があること
if(subject
&& verb
&& (verb->frPart & FR_PART_VERB));
else return(FALSE);
if(verb->object1) {
ReconsiderRecursiveObject(subject, verb->object1); // さらに動詞を目的語としてとっていた場合
if(verb->object1->frPart == FR_PART_PREPOSIT_A_INF)
hit |= CheckRecursiveObj(subject, verb->object1->child);
else if(verb->object1->frPart == FR_PART_PREPOSIT_DE_INF)
hit |= CheckRecursiveObj(subject, verb->object1->child);
else if(verb->object1->frPart == FR_PART_VERB_GENERAL)
hit |= CheckRecursiveObj(subject, verb->object1);
}
if(verb->object2) {
ReconsiderRecursiveObject(subject, verb->object2); // さらに動詞を目的語としてとっていた場合
if(verb->object2->frPart == FR_PART_PREPOSIT_A_INF)
hit |= CheckRecursiveObj(subject, verb->object2->child);
else if(verb->object2->frPart == FR_PART_PREPOSIT_DE_INF)
hit |= CheckRecursiveObj(subject, verb->object2->child);
else if(verb->object2->frPart == FR_PART_VERB_GENERAL)
hit |= CheckRecursiveObj(subject, verb->object2);
}
return(hit);
}
BOOL
CheckRecursiveObj(TOKEN *subject, TOKEN *verb)
{
if(verb
&& verb->frPart == FR_PART_VERB_GENERAL
&& verb->frTense == FR_TENSE_ORIGIN) {
if((verb->object1 && ConsiderRecursiveObject(subject, verb->object1)
|| (verb->object2 && ConsiderRecursiveObject(subject, verb->object2)))) {
SelectJpVerb2(subject, verb);
return(TRUE);
}
}
return(FALSE);
}
//
// JP_HINTを用いて、日本語訳を向上させる
//
void
ProcessJpHint(TOKEN *subject, TOKEN *verb)
{
if(subject == NULL || verb == NULL)
return;
JP_VERB *jpVerb = (JP_VERB *)verb->which;
if(jpVerb == NULL) return;
if((jpVerb->jpHint & JP_HINT_SVA)
&& (verb->object1)) {
ProcessJpHint_SVA(subject, verb);
}
if((jpVerb->jpHint & JP_HINT_VOLUME1_ADVERB)
&& (verb->object1) // 姉妹しか一人いない -> 一人の姉妹しかいない
&& (verb->object1->jpEmphasis & JP_EMPHASIS_ONLY) == 0) {
MoveVolumeToAdverb(verb, verb->object1);
}
if((jpVerb->jpHint & JP_HINT_PLACE_OBJECT1)
&& verb->object1) { // 私はあそこに店を見る -> 私はあそこの店を見る
TOKEN *adverb = DisconnectChildToken(verb, FR_PART_ADVERB_ALL, JP_PROP_PLACE);
if(adverb) {
AddChildTOKEN(verb->object1, adverb);
SelectJpAdverb2(verb->object1, adverb, NULL);
}
}
if((jpVerb->jpHint & JP_HINT_PLACE1_ADVERB)
&& verb->object1) {
TOKEN *prep = DisconnectChildToken(verb->object1, FR_PART_PREPOSIT_ALL, JP_PROP_PLACE);
if(prep == NULL)
prep = DisconnectChildToken(verb->object1, FR_PART_PREPOSIT_DE, JP_PROP_PLACE);
if(prep) {
AddChildTOKEN(verb, prep);
SelectJpPreposition2(verb, prep);
prep->jpEmphasis |= JP_EMPHASIS_COMMA;
}
}
if((jpVerb->jpHint & JP_HINT_TIME1_ADVERB)
&& verb->object1) {
TOKEN *prep = DisconnectChildToken(verb->object1, FR_PART_PREPOSIT_ALL, JP_PROP_TIME);
if(prep) {
AddChildTOKEN(verb, prep);
SelectJpPreposition2(verb, prep);
prep->jpEmphasis |= JP_EMPHASIS_COMMA;
}
}
if((jpVerb->jpHint & JP_HINT_TIME1_ADVERB)
&& verb->object1) {
TOKEN *prep = DisconnectChildToken(verb->object1, FR_PART_PREPOSIT_ALL, JP_PROP_TIME);
if(prep) {
AddChildTOKEN(verb, prep);
SelectJpPreposition2(verb, prep);
prep->jpEmphasis |= JP_EMPHASIS_COMMA;
}
}
if((jpVerb->jpHint & JP_HINT_AUXILIARY)
&& verb->object1) {
TOKEN *child, *object = verb->object1;
if((object->frPart & FR_PART_PREPOSIT)
&& object->object1)
object = object->object1; // A_INF, DE_INF
child = object->child;
object->child = NULL;
if(child) {
AddChildTOKEN(verb, child);
}
}
if((subject->frPart & FR_PART_NOUN)
&& !(jpVerb->jpHint & JP_HINT_SVA)) { // SVAは、すでに処理済み
// && !(jpVerb->jpHint & JP_HINT_PUTTOGETHER12)) {
SelectJpNoun(verb, subject, verb, jpVerb->jpProp0);
if(jpVerb->jpHint & JP_HINT_HUMAN) {
SelectJpNoun(verb, subject, verb, JP_PROP_HUMAN, jpVerb->jpProp0);
if(!(subject->jpProp & JP_PROP_HUMAN))
subject->scoreCombine += SCORE_STRANGE_SUBJECT;
}
}
if((verb->jpProp & JP_PROP_PASSIVE)
&& (jpVerb->jpHint & JP_HINT_HUMAN)) {
TOKEN *par = SearchToken(FR_PART_PREPOSIT_PAR, verb->child);
if(par)
SelectJpNoun(verb, par->object1, verb, JP_PROP_HUMAN);
else {
TOKEN *de = SearchToken(FR_PART_PREPOSIT_DE, verb->child);
if(de) SelectJpNoun(verb, de->object1, verb, JP_PROP_HUMAN);
}
}
if((jpVerb->jpHint & JP_HINT_DATE_SUBJECT)
&& verb->object1) { // c'etais mendi heir 昨日、月曜日だった -> 昨日は月曜日だった
TOKEN *adverb = SearchToken(FR_PART_ADVERB_ALL, JP_PROP_TIME, verb->child);
if(adverb == NULL)
adverb = SearchToken(FR_PART_ADVERB_ALL, JP_PROP_TIME, verb->child);
if(adverb) {
adverb->jpEmphasis |= JP_EMPHASIS_HA;
// 昨日は、月曜日だった -> 昨日は月曜日だった eg) Hier c'{tait dimanche.
adverb->jpEmphasis -= JP_EMPHASIS_COMMA;
}
}
if(jpVerb->jpHint & JP_HINT_COMPARE1) {
// ビールよりも私はとてもワインが好きだ -> ビールよりも私はワインが好きだ
TOKEN *mieux = SearchToken(FR_PART_ADVERB_COMPARE, verb->child);
if(mieux) {
mieux->prtControl = PRT_CONTROL_DISABLE;
if(verb->object1) verb->object1->jpEmphasis |= JP_EMPHASIS_HOU;
}
}
if(jpVerb->jpHint & JP_HINT_COMPARE2) {
// ビールよりも私はとてもワインが好きだ -> ビールよりも私はワインが好きだ
TOKEN *mieux = SearchToken(FR_PART_ADVERB_COMPARE, verb->child);
if(mieux) {
mieux->prtControl = PRT_CONTROL_DISABLE;
if(verb->object2) verb->object2->jpEmphasis |= JP_EMPHASIS_HOU;
}
}
if((verb->object1)
&&(jpVerb->jpHint & JP_HINT_SUCCEED_TENSE1)) { // あなたは私を手伝った必要がある -> あなたは私を手伝う必要があった
verb->frTense = verb->object1->frTense;
verb->object1->frTense = FR_TENSE_PRESENT;
}
if((verb->object1)
&&(jpVerb->jpHint & JP_HINT_DUMMY_NEGATIVE1)) { // 虚辞の<ne>
verb->object1->jpProp &= (~JP_PROP_NEGATIVE);
if(verb->object1->object2)
verb->object1->object2->jpProp &= (~JP_PROP_NEGATIVE);
}
if((verb->object1)
&&(jpVerb->jpHint & JP_HINT_RSUBJECT1)) {
TOKEN *rv = SearchToken(FR_PART_RELATIVE_SUBJECT, verb->object1->child);
if(rv
&& rv->object1
&& IsObjectMatch(rv->object1, FR_PART_VERB_ALL)) {
DisconnectChildToken(verb->object1, FR_PART_RELATIVE_SUBJECT, JP_PROP_NONE);
verb->object2 = rv->object1;
verb->object2->frTense = FR_TENSE_ORIGIN;
// verb->object2->frTense = (FR_TENSE)(verb->object2->frTense | FR_TENSE_ORIGIN);
SelectJpVerb2(subject, verb);
}
}
if(jpVerb->jpHint & JP_HINT_NO_NEGATIVE) {
verb->jpProp &= ~JP_PROP_NEGATIVE;
verb->jpProp &= ~JP_PROP_NEGATIVE2;
}
}
void
ProcessJpHint_SVA(TOKEN *subject, TOKEN *verb)
{
JP_VERB *jpVerb = (JP_VERB *)verb->which;
if(jpVerb == NULL) return;
do {
if(IsObjectMatch(verb->object1, FR_PART_NOUN_OBJECT_D)
&& verb->object1->frAttrib == FR_ATTRIB_IL)
ImproveJapanese(subject, verb->object1, verb, JP_PROP_THING, jpVerb->jpProp0); // nous le somme. 私もそれだ
else
ImproveJapanese(subject, verb->object1, verb, subject->jpProp, jpVerb->jpProp1);
if(jpVerb->jpHint & JP_HINT_HUMAN)
ImproveJapanese(subject, subject, verb, JP_PROP_HUMAN, jpVerb->jpProp0);
else
ImproveJapanese(subject, subject, verb, verb->object1->jpProp, jpVerb->jpProp0);
if(IsObjectMatch(verb->object1, FR_PART_ADJECTIVE_GENERAL)) // Paul est grand. ポールは偉大だ -> 大きい
PrioritizeBehindAdjective(verb->object1, subject, jpVerb->jpProp1);
} while(FlipCmpAdjective(verb, verb->object1)); // le moins -> le plus
}
//
// 名詞を修飾していた数詞を動詞修飾にする
// eg) 私は一台の車を持っている -> 私は車を一台持っている。
void
MoveVolumeToAdverb(TOKEN *verb, TOKEN *obj)
{
if(verb == NULL || obj == NULL || obj->child == NULL) return;
TOKEN *num = SearchToken(FR_PART_NUMETRIC_NUMBER, obj->child);
if(num == NULL) return; // 数詞はない
DisconnectChildToken(obj, num);
AddChildTOKEN(verb, num);
// 1台<の>車を持っている -> 車を1台持っている
num->jpEmphasis |= JP_EMPHASIS_NOTAIL;
}
//
// 動詞句(命令形) → 文章
//
void
ChangeOrderVerbToSentence(TOKEN *start)
{
TOKEN *p = start;
TOKEN *lastVerb = NULL;
// 文末が"?"で終わっている
if(currentTree->punctuation == FR_PUNCT_QUESTION) return;
for(p = start; p; p = p->next) {
if(p->frPart & FR_PART_COMBINE)
continue;
if(p->frPart & FR_PART_VERB)
lastVerb = p; // 動詞が2つ以上有る
if((p->frPart & FR_PART_SPECIAL)
&& p->frPart != FR_PART_SPECIAL_COMMA)
lastVerb = NULL; // 未解決の単語が残っている
}
if(lastVerb == NULL) return;
p = start->next;
if( p
&& p->subject == NULL
&& p == lastVerb // ただ1つの動詞があること
&& (p->frPart & FR_PART_VERB)
&& p->which) {
if(p->frTense & FR_TENSE_ORDER) {
if(p->frAttrib & (FR_ATTRIB_LEVEL1 | FR_ATTRIB_LEVEL2)) // 命令形で3人称はない
p->frAttrib = (FR_ATTRIB)(p->frAttrib & ~FR_ATTRIB_LEVEL3);
if(!(p->frAttrib & FR_ATTRIB_PLURAL)) // 単数形なら2人称のはず eg) Leve-toi. Leveは1,2,3単
p->frAttrib = (FR_ATTRIB)(p->frAttrib & ~FR_ATTRIB_LEVEL1);
ChangeOrderVerbToSentence(start, lastVerb);
} else if((p->frTense & FR_TENSE_ORIGIN)
&& (p->frPartChoice & FR_PART_INDEPENDENCE)) {
ChangeOrderVerbToSentence(start, lastVerb);
}
}
}
void
ChangeOrderVerbToSentence(TOKEN *start, TOKEN *verb)
{
const static char *dummystr = "命令文";
TOKEN *subject = PutToken(FR_PART_NOUN_SUBJECT,
verb->frAttrib, JP_PROP_HUMAN, &dummystr); // 命令形なのだから 主語は人?
subject->prtControl = PRT_CONTROL_DISABLE; // dummy subjectは表示しない
verb->frPart = (FR_PART)(verb->frPart | FR_PART_SENTENCE_ORDER);
verb->subject = subject; // 動詞
verb->scoreCombine += SCORE_MAKE_ORDER;
ChangeVerbTenseToOrder(verb);
SelectJpVerb2(subject, verb); // まずは、命令形専用の辞書
// 目的語に動詞を持つ場合 eg) allez vous laver les mains.
ReconsiderRecursiveObject(subject, verb);
}
void
ChangeVerbTenseToOrder(TOKEN *verb)
{
if(verb->frPart & FR_PART_COMBINE) {
if(verb->object1)
ChangeVerbTenseToOrder(verb->object1);
if(verb->object2)
ChangeVerbTenseToOrder(verb->object2);
return;
}
if(verb->frTense & FR_TENSE_ORIGIN)
verb->frTense = (FR_TENSE)(FR_TENSE_ORIGIN | FR_TENSE_ORDER);
else
verb->frTense = FR_TENSE_ORDER;
}
//
// 動詞句+ 目的語 → 動詞句
//
void
CombineVerbObject(TOKEN *start)
{
TOKEN *p;
TOKEN *lastVerb = NULL;
// 後ろにある動詞から解析を始める
for(p = start; p; p= p->next) {
if((p->frPart & FR_PART_VERB)
&& p->subject == NULL // 主語なし
&& !(p->frPart & FR_PART_COMBINE)
&& p->which == NULL
&& !(p->frTense == FR_TENSE_ORIGIN && p->which) // aller + inf -> 近未来 allerに注目する必要がある
&& !(p->frTense == FR_TENSE_P_PAST && p->which)) { // etre + pp -> 受動態 etreに注目する必要がある
lastVerb = p;
}
// なんか問題になるような条件があったら、ここでlastVerb = NULL;する
if(ToWaitCombineVerbObject(p, lastVerb))
lastVerb = NULL;
}
if(lastVerb != NULL && lastVerb->which == NULL) {
if(lastVerb->next
&& lastVerb->preposition
&& MatchAdjectiveObject(lastVerb->next, lastVerb->preposition)) {
// orthographe de laquelle vous ne serez pas s~r.
// -> orthographe laquelle vous ne serez <de+NULL> pas s~r.
// -> orthographe laquelle vous ne serez pas s~r <de+NULL>
CombineAdjectiveObject(start, lastVerb->next, lastVerb->preposition);
lastVerb->preposition = NULL;
} else {
SelectJpVerb1(lastVerb);
if(lastVerb->which) {
// 動詞の訳を選んだら、副詞も検討し直す
ImproveJapanese(lastVerb, lastVerb->child, lastVerb, JP_PROP_ALL, JP_PROP_ALL);
}
}
}
}
//
// 動詞 + 目的語の連結を待つべきか?
//
BOOL
ToWaitCombineVerbObject(TOKEN *p, TOKEN *verb)
{
// 通すもの
if(p->frPart == FR_PART_SPECIAL_COMMA
|| p->frPart == FR_PART_SPECIAL_AUSSI)
return(FALSE);
// 主語が確定していれば通す
if(p->subject) {
if(p->frPart == FR_PART_SENTENCE_QUE
|| p->frPart == FR_PART_SENTENCE_ORIGIN)
return(FALSE);
}
// 問答無用
if((p->frPart & FR_PART_RELATIVE)
|| p->frPart == FR_PART_INTERROGATIVE_UNCLEAR
|| (p->frPart & FR_PART_SPECIAL))
return(TRUE);
// object1 = object2 = NULLなら
if(p->object1 == NULL && p->object2 == NULL) {
if(p->frPart & FR_PART_PREPOSIT)
return(TRUE);
}
if(p->object1 == NULL || p->object2 == NULL) {
if(p->frPart == FR_PART_COMBINE_NOUN
|| p->frPart == FR_PART_COMBINE_ADJECTIVE
|| p->frPart == FR_PART_COMBINE_PREPOSIT)
return(TRUE);
}
return(FALSE);
}
//
// 動詞の適当な日本語訳を選ぶ
//
void
SelectJpVerb1(TOKEN *verb)
{
if((verb->frTense & FR_TENSE_PASSIVE)
|| (verb->frTense == FR_TENSE_P_PAST)) {
verb->which = NULL; // 候補をクリア
SelectJpVerb1_Passive(verb, TRUE); // 受動態専用の候補のみ
if(verb->which == NULL)
SelectJpVerb1_Passive(verb, FALSE); // 一般的な訳も候補に入れる
}
if(verb->which == NULL) {
// 受動態の訳がなければ、能動態の訳を探す
SelectJpVerb1_Active(verb);
}
if(verb->which) {
JP_VERB *jpVerb = (JP_VERB *)verb->which;
JP_PROP savProp = verb->jpProp * (~JP_PROP_ALL);
verb->jpProp = savProp | jpVerb->myJpProp;
if(verb->object1) JpVerbPostProcess1(verb, verb->object1, jpVerb->jpProp1);
if(verb->object2) JpVerbPostProcess1(verb, verb->object2, jpVerb->jpProp2);
// il accepte de venir avec nous. (avec nousはaccepteではなくvenirに掛るべき)
TOKEN *next = verb->next;
#if 1
if(next) {
if(VerbObjectPreposition(verb, verb->object2) == FALSE) {
VerbObjectPreposition(verb, verb->object1);
}
}
#endif
for(TOKEN *q = verb->child; q; q = q->next)
q->scoreCombine += SCORE_INSERTED_ADVERB;
}
}
//
// SelectJpVerb1の後処理
//
void
JpVerbPostProcess1(TOKEN *verb, TOKEN *object, JP_PROP jpProp)
{
if(object->frPart & FR_PART_COMBINE) {
JpVerbPostProcess1(verb, object->object1, jpProp);
JpVerbPostProcess1(verb, object->object2, jpProp);
return;
}
JpVerbPostProcess(verb, object, jpProp);
if(object->frPart & FR_PART_PREPOSIT) {
object->scoreCombine += SCORE_VERB_PREPOSITION;
}
// 一般名詞を冠詞/所有形容詞無しで使ったな -> 減点
if(IsObjectMatch(object, FR_PART_NOUN_GENERAL)
&& !HasArticleOrUnique(object)) {
object->scoreCombine += SCORE_NO_ARTICLE_NOUN;
}
if(CheckUnnaturalObject(object)) {
verb->scoreSelect = 0; // いくら動詞が良い訳でもねぇ...
object->scoreCombine += SCORE_VERB_STRANGE_OBJECT;
}
}
void
JpVerbPostProcess(TOKEN *verb, TOKEN *object, JP_PROP jpProp)
{
if(object->frPart & FR_PART_COMBINE) {
JpVerbPostProcess(verb, object->object1, jpProp);
JpVerbPostProcess(verb, object->object2, jpProp);
return;
}
// 日本語訳に前置詞が含まれていた場合外す。
if(object->frPart & FR_PART_PREPOSIT) {
// 前置詞ではなく、名詞を選択する。
TOKEN *noun = object->object1;
SelectJpNoun(verb, noun, verb, jpProp);
SetPrtControlReplace(object);
// il ne fait pitie a personne. personneの"誰<にも>"を動詞に伝える
if(object->object1)
object->jpEmphasis = object->object1->jpEmphasis;
} else if(object->frPart & FR_PART_VERB) {
// nous devons ]tre fatigue.
object->frTense = (FR_TENSE)(object->frTense & ~FR_TENSE_ORDER);
if(IsObjectMatch(object, FR_PART_SENTENCE_QUE))
object->prtControl = PRT_CONTROL_REPLACED;
} else if(IsObjectMatch(object, FR_PART_NOUN_OBJECT_D, JP_PROP_NONE, NULL, "en")) {
object->prtControl = PRT_CONTROL_DISABLE;
}
if(CheckUnnaturalObject(object)) {
verb->scoreSelect = 0; // いくら動詞が良い訳でもねぇ...
}
}
void
SetPrtControlReplace(TOKEN *p)
{
if(p->prtControl == PRT_CONTROL_ENABLE) {
if(p->frPart & FR_PART_COMBINE) {
if(p->object1) SetPrtControlReplace(p->object1);
if(p->object2) SetPrtControlReplace(p->object2);
} else {
p->prtControl = PRT_CONTROL_REPLACED;
}
}
}
//
// 動詞の目的語としてより、副詞の方が似合っているもの
// (Il est juste) dix heures -> Il est (juste) dix heures.
//
char *unnaturalObjects[] = {
"aujourd'hui",
"encore",
"juste",
"toujours",
"tous",
"tout",
"" // End Code
};
BOOL
CheckUnnaturalObject(TOKEN *p)
{
for(int i = 0; unnaturalObjects[i][0]; i++) {
if(IsTokenFrench(p, unnaturalObjects[i]))
return(TRUE);
}
return(FALSE);
}
//
// Verb + Object 後続の前置詞の処理
// eg) il accepte de venir avec nous
// avec nousは accepteではなく venirに掛るべき
//
BOOL
VerbObjectPreposition(TOKEN *verb, TOKEN *object)
{
if(verb == NULL
|| verb->next == NULL
|| object == NULL)
return(FALSE);
TOKEN *next = verb->next;
if(object->frPart == FR_PART_PREPOSIT_A_INF
|| object->frPart == FR_PART_PREPOSIT_DE_INF)
object = object->object1;
if(object == NULL) return(FALSE);
if((next->frPart & FR_PART_PREPOSIT)
&& MatchParentPreposition(object, next)) {
CombineParentPreposition(verb, object, next);
return(TRUE);
}
return(FALSE);
}
// 動詞の適当な日本誤訳を選ぶ(能動態)
// (構文解析のため、後でCombineSubjectVerb()関数で
// propを踏まえて再び最適な日本語を選ぶ)
void
SelectJpVerb1_Active(TOKEN *verb)
{
JP_VERB const *jpVerb = ((VERB *)verb->what)->jpVerb;
int proposed = ((VERB *)verb->what)->proposed;
TOKEN *obj1 = verb->next;
TOKEN *obj2 = NULL;
TOKEN *hitObj1 = NULL, *hitObj2 = NULL;
if(obj1 != NULL) obj2 = verb->next->next;
while(proposed-- > 0) {
int cmp = -1;
if(verb->frCompose != FR_COMPOSE_NONE
&& verb->frCompose != jpVerb->frCompose)
goto NotMatch;
if(verb->preposition != NULL) {
// 前置詞つきの関係代名詞から、前置詞を引き継いだ場合
cmp = CmpVerbObject(jpVerb, obj1, verb->preposition);
if(cmp >= 1) hitObj1 = obj1;
if(cmp >= 2) hitObj2 = verb->preposition;
if(cmp < 0) {
cmp = CmpVerbObject(jpVerb, verb->preposition, obj1);
if(cmp >= 1) hitObj1 = verb->preposition;
if(cmp >= 2) hitObj2 = obj1;
}
} else {
int savCmp = cmp = CmpVerbObject(jpVerb, obj1, obj2);
if(cmp >= 1) hitObj1 = obj1;
if(cmp >= 2) hitObj2 = obj2;
if(cmp <= 0 ) {
// && jpVerb->frPart2 != FR_PART_NONE) {
// 順序を変えて再検査
cmp = CmpVerbObject(jpVerb, obj2, obj1);
if(cmp == 2) {
hitObj1 = obj2;
hitObj2 = obj1;
} else if(cmp == 1
&& (obj1->frPartParent & FR_PART_VERB)
&& (IsObjectMatch(obj1, FR_PART_PREPOSIT_ALL) || IsObjectMatch(obj1, FR_PART_ADVERB_ALL))) {
hitObj1 = obj2;
hitObj2 = NULL;
obj1->frPartParent = FR_PART_VERB;
// Elle parle (le plus souvent) de la classe.
// -> Elle parle de la classe (le plus souvent)
// は、ちょっと不自然
obj1->scoreCombine += SCORE_INSERTED_ADVERB;
} else
cmp = savCmp; // 0 or -1
// else cmp = -1; // cmp == 1は、無視する
}
}
if(cmp < 0) goto NotMatch;
// !! BINGO !!
if(hitObj1) {
ChangeProperObject(hitObj1, jpVerb->frPart1, jpVerb->jpProp1);
ConsiderRecursiveObject(verb, hitObj1);
if(hitObj1 == verb->preposition) verb->preposition = NULL;
else DisconnectTOKEN(verb, hitObj1);
verb->object1 = hitObj1;
}
if(hitObj2) {
ChangeProperObject(hitObj2, jpVerb->frPart2, jpVerb->jpProp2);
ConsiderRecursiveObject(verb, hitObj2);
if(hitObj2 == verb->preposition) verb->preposition = NULL;
else DisconnectTOKEN(verb, hitObj2);
verb->object2 = hitObj2;
}
// 辞書にヒットしなかった前置詞を復帰
if(verb->preposition) GetBackPreposition(verb);
verb->scoreSelect = proposed * SCORE_SELECT_VERB;
UpdateJpVerb(verb, jpVerb);
isChanged = TRUE;
return;
NotMatch:
jpVerb++;
}
/*
まだ目的語が後に来る可能性がある
e.g) c'est la voiture que vous avez achet{e.
cerr << "Internal Error <SelectJpVerb1>" << endl;
TermProgram(-1);
*/
}
int
CmpVerbObject(const JP_VERB *jpVerb, TOKEN *obj1, TOKEN *obj2)
{
int cntHit = 0;
if(jpVerb->SEval) {
// 主語チェックのあるものは、ここでははじく
// SelectJpVerb2で復活させる
return(-1);
} else if(jpVerb->frPart1 != FR_PART_NONE) {
if(obj1 == NULL) return(-1);
if(obj1->frPart == FR_PART_PREPOSIT_DE
&& jpVerb->frPart1 == FR_PART_PREPOSIT_ALL)
return(-1);
if(!IsObjectMatch(obj1, FR_PART_INTERROGATIVE_ALL)
&& IsObjectMatch(obj1, FR_PART_NOUN_OBJECT_BOTH)
&& obj1->moved != 1)
return(-1); // 本当は人称代名詞を探していた
if(CompareObject(obj1, jpVerb->frPart1, jpVerb->jpProp1, jpVerb->OEval1, jpVerb->str1)) {
cntHit++;
} else return(-1);
}
if(jpVerb->frPart2 != FR_PART_NONE) {
if(obj2 == NULL) return(-1);
if(obj2->frPart == FR_PART_PREPOSIT_DE
&& jpVerb->frPart2 == FR_PART_PREPOSIT_ALL)
return(-1);
if(!IsObjectMatch(obj2, FR_PART_INTERROGATIVE_ALL)
&& IsObjectMatch(obj2, FR_PART_NOUN_OBJECT_BOTH)
&& obj2->moved != 1)
return(-1); // 本当は人称代名詞を探していた
if(CompareObject(obj2, jpVerb->frPart2, jpVerb->jpProp2, jpVerb->OEval2, jpVerb->str2)) {
cntHit++;
} else return(-1);
}
return(cntHit);
}
BOOL
CompareObject(TOKEN *p, FR_PART frPart, JP_PROP jpProp, BOOL (*Eval)(TOKEN *), char *str)
{
if(p == NULL
|| !(p->frPartChoice & FR_PART_OBJECT))
return(FALSE); // これは、動詞の目的語にならない
if((p->frPart & FR_PART_COMBINE)
&& (p->frPart & FR_PART_PREPOSIT)) {
frPart = (FR_PART)(frPart | FR_PART_COMBINE);
}
return(IsObjectMatch(p, frPart, jpProp, Eval, str));
}
//
// CombineVerbObejct処理後、行き場のない前置詞を復活する
//
void
GetBackPreposition(TOKEN *verb)
{
TOKEN *preposition = verb->preposition;
if(preposition == NULL) return;
verb->preposition = NULL;
// 後ろ(object2)から検索
if(verb->object2
&& SelectJpPreposition2(verb->object2, preposition)) {
AddChildTOKEN(verb->object2, preposition);
} else if(verb->object1
&& SelectJpPreposition2(verb->object1, preposition)) {
AddChildTOKEN(verb->object1, preposition);
} else {
InsertTOKEN(verb, preposition);
}
}
// 動詞の適当な日本誤訳を選ぶ(受動態)
// (構文解析のため、後でCombineSubjectVerb()関数で
// propを踏まえて再び最適な日本語を選ぶ)
// passiveVoiceOnly : JP_PROP_PASSIVEのみを相手にするか?
void
SelectJpVerb1_Passive(TOKEN *verb, BOOL passiveVoiceOnly)
{
JP_VERB const *jpVerb = ((VERB *)verb->what)->jpVerb;
int proposed = ((VERB *)verb->what)->proposed;
TOKEN *de_subject = NULL; // par ~, de~などの動作主
TOKEN *object2;
while(proposed-- > 0) {
if(passiveVoiceOnly
&& (jpVerb->myJpProp & JP_PROP_PASSIVE) == 0)
goto NotMatch;
object2 = NULL;
// 非人称主語は受け身をとらない
if(jpVerb->frPart0 == FR_PART_NOUN_IMPERSONAL
|| jpVerb->frPart1 == FR_PART_NOUN_RECURSIVE)
goto NotMatch;
// 受け身になるのは、名詞だけ
if((jpVerb->frPart1 & FR_PART_NOUN) == FR_PART_NONE)
goto NotMatch;
if(jpVerb->frPart2 != FR_PART_NONE) {
object2 = GetProperObject(verb, jpVerb->frPart2, jpVerb->jpProp2);
if(object2 == NULL) goto NotMatch;
}
// !! BINGO !!
if(object2) {
ChangeProperObject(object2, jpVerb->frPart2, jpVerb->jpProp2);
DisconnectTOKEN(verb, object2);
}
UpdateJpVerb(verb, jpVerb);
verb->scoreSelect = 0;
verb->jpProp |= JP_PROP_PASSIVE;
verb->object1 = NULL;
verb->object2 = object2;
verb->frTense = (FR_TENSE)(verb->frTense | FR_TENSE_PASSIVE);
isChanged = TRUE;
// もしあれば、動作主を探す
do {
if(verb->jpProp & JP_PROP_ACTION) {
de_subject = SearchToken(FR_PART_PREPOSIT_PAR, verb);
if(IsObjectMatch(de_subject, FR_PART_NOUN_OBJECT_BOTH)) de_subject = NULL; // me, te, ...
}
if(de_subject == NULL) {
de_subject = SearchToken(FR_PART_PREPOSIT_DE, verb);
if(IsObjectMatch(de_subject, FR_PART_NOUN_OBJECT_BOTH)) de_subject = NULL; // me, te, ...
}
} while(de_subject && de_subject == object2); // de_subject = object2 == NULLは通す
if(de_subject) {
AttatchParentPreposition(verb, verb, de_subject);
de_subject->scoreCombine += SCORE_PASSIVE_SUBJECT;
}
return;
NotMatch:
jpVerb++;
}
/*
まだ目的語が後に来る可能性がある
e.g) c'est la voiture que vous avez achet{e.
cerr << "Internal Error <SelectJpVerb1>" << endl;
TermProgram(-1);
*/
}
//
// 受動態の処理 (etre + 過去分詞) -> 受身
//
void
ProcessPassiveVoice(TOKEN *start)
{
TOKEN *p;
TOKEN *lastEtre = NULL, *lastVerb = NULL;
for(p = start; p; p = p->next) {
if(p->frPart & FR_PART_COMBINE)
continue;
else if(p->subject)
continue;
else if(IsObjectMatch(p, FR_PART_VERB, JP_PROP_NONE, NULL, "]tre"))
lastEtre = p;
else if(p-> frPart & FR_PART_VERB)
lastVerb = p;
}
if(lastEtre
&& lastEtre->which == NULL
&& lastVerb
&& lastVerb->which
&& (lastVerb->frTense & FR_TENSE_PASSIVE)
&& lastEtre->next == lastVerb)
CombineEtrePastParticiple(start, lastEtre, lastVerb);
}
const JP_VERB
*MatchVerbObject(TOKEN *verb, TOKEN *object1, TOKEN *object2)
{
const JP_VERB *jpVerb = ((VERB *)verb->what)->jpVerb;
int proposed = ((VERB *)verb->what)->proposed;
while(proposed-- > 0) {
int cmp = CmpVerbObject(jpVerb, object1, object2);
if(cmp == 2)
return(jpVerb);
if(cmp <= 0
&& CmpVerbObject(jpVerb, object2, object1) == 2)
return(jpVerb);
jpVerb++;
}
return(NULL);
}
void
SelectJpVerb2(TOKEN *subject, TOKEN *verb)
{
if(verb->frPart & FR_PART_COMBINE) {
if(verb->object1)
SelectJpVerb2(subject, verb->object1);
if(verb->object2)
SelectJpVerb2(subject, verb->object2);
return;
}
// 否定、疑問、受動態などの情報
JP_PROP savJpProp = (JP_PROP)(verb->jpProp * ~JP_PROP_ALL);
if(verb->frTense == FR_TENSE_ORDER) { // 命令形
verb->which = NULL;
SelectJpVerb2_Order(verb, TRUE); // 命令形専用の候補のみ
if(verb->which == NULL)
SelectJpVerb2_Order(verb, FALSE); // 一般的な訳も候補に入れる
} else if((verb->frTense & FR_TENSE_PASSIVE)
|| (verb->frTense & FR_TENSE_ETRE_PASSIVE)) { // 受動態
SelectJpVerb2_Passive(subject, verb);
verb->jpProp |= JP_PROP_PASSIVE;
} else
SelectJpVerb2_Active(subject, verb);
if(verb->which == NULL) {
currentTree->prtControl = PRT_CONTROL_DISABLE;
} else {
JP_VERB *jpVerb = (JP_VERB *)verb->which;
verb->jpProp = (JP_PROP)(jpVerb->myJpProp | savJpProp);
if(jpVerb->jpHint & JP_HINT_SVOA)
verb->scoreCombine += SCORE_VERB_SVOA;
if(verb->object1) JpVerbPostProcess(verb, verb->object1, jpVerb->jpProp1);
if(verb->object2) JpVerbPostProcess(verb, verb->object2, jpVerb->jpProp2);
}
}
void
SelectJpVerb2_Active(TOKEN *subject, TOKEN *verb)
{
JP_PROP mask = verb->jpProp * (JP_PROP_NEGATIVE | JP_PROP_PASSIVE);
verb->which = NULL;
SelectJpVerb2_Active(subject, verb, mask); // 否定形専用の候補のみ
if(verb->which == NULL) {
SelectJpVerb2_Active(subject, verb, JP_PROP_NONE);
}
}
void
SelectJpVerb2_Active(TOKEN *subject, TOKEN *verb, JP_PROP mask)
{
JP_VERB const *jpVerb = ((VERB *)verb->what)->jpVerb;
int proposed = ((VERB *)verb->what)->proposed;
while(proposed-- > 0) {
if(!(mask == JP_PROP_NONE || (jpVerb->myJpProp & mask)))
goto NotMatch;
if(jpVerb->frPart0 == FR_PART_NONE
&& subject)
goto NotMatch;
if(jpVerb->frPart0 != FR_PART_NONE) {
if(!subject
|| !IsObjectMatch(subject, jpVerb->frPart0, jpVerb->jpProp0, NULL, NULL)
|| (jpVerb->SEval && jpVerb->SEval(subject, verb) == FALSE))
goto NotMatch;
}
if(jpVerb->frPart1 != FR_PART_NONE) {
if(! CompareObject(verb->object1, jpVerb->frPart1, jpVerb->jpProp1, jpVerb->OEval1, jpVerb->str1))
goto NotMatch;
}
if(jpVerb->frPart2 != FR_PART_NONE) {
if(! CompareObject(verb->object2, jpVerb->frPart2, jpVerb->jpProp2, jpVerb->OEval2, jpVerb->str2))
goto NotMatch;
}
// すでに、複合過去形として処理されたもの
if(verb->frCompose != FR_COMPOSE_NONE
&& verb->frCompose != jpVerb->frCompose) {
verb->which = NULL; // この候補は無効
goto NotMatch;
}
verb->scoreSelect = proposed * SCORE_SELECT_VERB;
UpdateJpVerb(verb, jpVerb);
return;
NotMatch:
jpVerb++;
}
// verb->score = SCORE_UNCLEAR_WORD;
}
void
SelectJpVerb2_Passive(TOKEN *subject, TOKEN *verb)
{
JP_PROP mask = verb->jpProp * (JP_PROP_NEGATIVE | JP_PROP_PASSIVE);
verb->which = NULL;
SelectJpVerb2_Passive(subject, verb, mask); // 受動態専用の候補のみ
if(verb->which == NULL) {
mask &= ~JP_PROP_PASSIVE;
SelectJpVerb2_Passive(subject, verb, mask); // 一般的な訳も候補に入れる
}
if(verb->which == NULL) {
SelectJpVerb2_Passive(subject, verb, JP_PROP_NONE); // 一般的な訳も候補に入れる
}
}
void
SelectJpVerb2_Passive(TOKEN *subject, TOKEN *verb, JP_PROP mask)
{
JP_VERB const *jpVerb = ((VERB *)verb->what)->jpVerb;
int proposed = ((VERB *)verb->what)->proposed;
// 動作主
TOKEN *par = SearchToken(FR_PART_PREPOSIT_PAR, verb->child);
if(par == NULL) par = SearchToken(FR_PART_PREPOSIT_DE, verb->child);
if(par) par = par->object1;
while(proposed-- > 0) {
if(!(mask == JP_PROP_NONE || (jpVerb->myJpProp & mask)))
goto NotMatch;
if(jpVerb->frPart0 == FR_PART_NONE
|| jpVerb->frPart0 == FR_PART_NOUN_IMPERSONAL // 非人称主語は受け身をとらない
|| jpVerb->frPart1 == FR_PART_NONE // 他動詞のみ考慮
|| jpVerb->frPart1 == FR_PART_NOUN_RECURSIVE)
goto NotMatch;
if(par
&& jpVerb->str0 // 変な指定があった場合
&& !IsObjectMatch(par, jpVerb->frPart0, jpVerb->jpProp0, NULL, jpVerb->str0))
goto NotMatch;
if(subject != NULL
&& !IsObjectMatch(subject, jpVerb->frPart1, jpVerb->jpProp1, NULL, NULL))
goto NotMatch;
if(jpVerb->frPart2 != FR_PART_NONE) {
if(! CompareObject(verb->object2, jpVerb->frPart2, jpVerb->jpProp2, jpVerb->OEval2, jpVerb->str2))
goto NotMatch;
}
if(verb->which != (void *)jpVerb) {
verb->which = (void *)jpVerb;
verb->jpProp = jpVerb->myJpProp;
isChanged = TRUE;
}
return;
NotMatch:
jpVerb++;
}
}
//
// 命令形動詞の日本語訳を探す
//
void
SelectJpVerb2_Order(TOKEN *verb, BOOL orderTenseOnly)
{
JP_VERB const *jpVerb = ((VERB *)verb->what)->jpVerb;
int proposed = ((VERB *)verb->what)->proposed;
while(proposed-- > 0) {
if(orderTenseOnly) {
if(jpVerb->frPart0 != FR_PART_NONE) goto NotMatch;
} else {
// やっぱり、命令は人に言うものでは...
if(!(jpVerb->frPart0 & FR_PART_NOUN)
|| !(jpVerb->jpProp0 & JP_PROP_HUMAN)
|| jpVerb->SEval) // 評価したいが主語はない
goto NotMatch;
}
if(jpVerb->frPart1 != FR_PART_NONE) {
if(! CompareObject(verb->object1, jpVerb->frPart1, jpVerb->jpProp1, jpVerb->OEval1, jpVerb->str1))
goto NotMatch;
} else if(verb->object1) goto NotMatch;
if(jpVerb->frPart2 != FR_PART_NONE) {
if(! CompareObject(verb->object2, jpVerb->frPart2, jpVerb->jpProp2, jpVerb->OEval2, jpVerb->str2))
goto NotMatch;
} else if(verb->object2) goto NotMatch;
verb->scoreSelect = proposed * SCORE_SELECT_VERB;
UpdateJpVerb(verb, jpVerb);
return;
NotMatch:
jpVerb++;
}
}
BOOL
UpdateJpVerb(TOKEN *p, JP_VERB const *jpVerb)
{
VERB *verb = (VERB *)p->what;
if((JP_VERB *)p->which != jpVerb) {
JP_PROP jpProp = (p->jpProp * ~JP_PROP_ALL);
p->which = (void *)jpVerb;
p->jpProp = (jpProp | jpVerb->myJpProp);
isChanged = TRUE;
return(TRUE);
}
return(FALSE);
}
TOKEN
*GetProperObject(TOKEN *p, FR_PART frPart, JP_PROP jpProp)
{
if(p == NULL || p->next == NULL) return(NULL);
p = SearchToken(frPart, p->next);
if(p
&& IsObjectMatch(p, frPart, jpProp, NULL, NULL))
return(p);
return(NULL);
}
//
// 再帰代名詞をチェック
//
BOOL
ConsiderRecursiveObject(TOKEN *verb, TOKEN *obj)
{
if(verb && obj // 動詞と目的語がある
&& (IsObjectMatch(obj, FR_PART_NOUN_OBJECT_D)
|| IsObjectMatch(obj, FR_PART_NOUN_OBJECT_I))
&& !IsObjectMatch(obj, FR_PART_NOUN_RECURSIVE)) {
FR_ATTRIB attrib = (FR_ATTRIB)(verb->frAttrib & obj->frAttrib);
if((attrib & (FR_ATTRIB_LEVEL1 | FR_ATTRIB_LEVEL2)) // 3人称は'se'(lui, leurなどは再帰代名詞ではない)
&& (attrib & (FR_ATTRIB_SINGLE | FR_ATTRIB_PLURAL))
&& (attrib & (FR_ATTRIB_MALE | FR_ATTRIB_FEMALE))) {
obj->frPart = (FR_PART)(obj->frPart | FR_PART_NOUN_RECURSIVE);
return(TRUE);
}
}
return(FALSE);
}
//
// 複合過去形を処理
// (深く吟味せず、安易に2つの候補を作成する)
//
void
ProcessComposePasse(TOKEN *start)
{
TOKEN *p = start;
TOKEN *lastEtre = NULL, *lastAvoir = NULL;
TOKEN *lastRien = NULL;
while(p) {
if(p->frPart & FR_PART_VERB) {
if(p->frTense & FR_TENSE_P_PAST) {
if(lastEtre) { // etre + pp
if(HasEtreCompose(p)) {
TOKEN *altP = CopyCurrentTree(p, "ProcessComposePasse");
p->frCompose = FR_COMPOSE_ETRE;
MakeComposePasse(start, lastEtre, p, lastRien); // 候補1 etre + pp -> 複合過去
altP->frTense = FR_TENSE_PASSIVE; // 候補2 etre + pp -> 受動態
} else {
p->frTense = FR_TENSE_PASSIVE; // 確定 etre + pp -> 受動態
lastEtre = NULL;
}
}
if(lastAvoir) { // avoir + pp -> 複合過去
p->frCompose = FR_COMPOSE_AVOIR;
MakeComposePasse(start, lastAvoir, p, lastRien);
}
if(lastRien) {
}
lastEtre = lastAvoir = lastRien = NULL;
} else if(IsObjectMatch(p ,FR_PART_VERB_GENERAL, JP_PROP_NONE, NULL, "]tre")
&& p->object1 == NULL && p->object2 == NULL) {
lastEtre = p; lastAvoir = NULL;
p = SkipSubject(p);
} else if(IsObjectMatch(p, FR_PART_VERB_GENERAL, JP_PROP_NONE, NULL, "avoir")
&& p->object1 == NULL && p->object2 == NULL) {
lastEtre = NULL; lastAvoir = p;
p = SkipSubject(p);
}
} else if(IsObjectMatch(p, FR_PART_NOUN_INDEFINIT, JP_PROP_NONE, NULL, "rien")) {
lastRien = p;
} else if(!IsObjectMatch(p, FR_PART_ADVERB_ALL)) {
// etreとppの間に副詞が入ることもある。 eg) je ne me suis pas lev{.
lastEtre = lastAvoir = lastRien = NULL;
}
p = p->next;
}
}
//
// 倒置形疑問文の主語を飛ばす
//
TOKEN
*SkipSubject(TOKEN *p)
{
if( p->next // le lui avez-vous donn{? vousを飛ばす
&& (p->punctuation & FR_PUNCT_HYPHEN)
&& IsObjectMatch(p->next, FR_PART_NOUN_SUBJECT)) {
p = p->next;
if(IsObjectMatch(p, FR_PART_NOUN_OBJECT_BOTH))
p->frPart = FR_PART_NOUN_SUBJECT;
}
return(p);
}
//
// 複合過去を作るのにetreを使う場合があるか?
//
BOOL
HasEtreCompose(TOKEN *p)
{
JP_VERB const *jpVerb = ((VERB *)p->what)->jpVerb;
int proposed = ((VERB *)p->what)->proposed;
while(proposed -- > 0) {
if(jpVerb->frCompose & FR_COMPOSE_ETRE) return(TRUE);
jpVerb++;
}
return(FALSE);
}
//
// JP_HINT_SVOAを持っているか?
//
BOOL
HasJpHintSVOA(TOKEN *p)
{
JP_VERB const *jpVerb = ((VERB *)p->what)->jpVerb;
int proposed = ((VERB *)p->what)->proposed;
while(proposed -- > 0) {
if(jpVerb->jpHint & JP_HINT_SVOA) return(TRUE);
jpVerb++;
}
return(FALSE);
}
//
//
//
BOOL
HasPrepositionObject(TOKEN *verb, TOKEN *prep)
{
if( verb == NULL
|| !(verb->frPart & FR_PART_VERB))
return(FALSE);
if(verb->frPart & FR_PART_COMBINE) {
if(verb->object2) verb = verb->object2;
else return(FALSE);
}
JP_VERB const *jpVerb = ((VERB *)verb->what)->jpVerb;
int proposed = ((VERB *)verb->what)->proposed;
while(proposed-- > 0) {
if(CompareObject(prep, jpVerb->frPart1, jpVerb->jpProp1, jpVerb->OEval1, jpVerb->str1)
|| CompareObject(prep, jpVerb->frPart2, jpVerb->jpProp2, jpVerb->OEval2, jpVerb->str2)) {
return(TRUE);
}
jpVerb++;
}
return(FALSE);
}
//
// 名詞 + 現在/過去分詞
//
void
CombineNounParticiple(TOKEN *start)
{
TOKEN *p = start;
TOKEN *lastNoun = NULL, *lastVerb = NULL;
while(p && p->next) {
TOKEN *next = p->next;
if(IsObjectMatch(p, FR_PART_NOUN_GENERAL) // 代名詞に分詞補語は付かない。一般名詞のみ
&& (next->frPart & FR_PART_VERB)
&& next->which
&& (next->frTense & (FR_TENSE)(FR_TENSE_PASSIVE | FR_TENSE_P_PAST | FR_TENSE_P_PRESENT))) {
// 名詞 + 過去分詞 or 名詞 + 現在分詞
lastNoun = p; lastVerb = next;
}
p = next;
}
if(lastVerb == NULL) return;
if(lastVerb->frTense & FR_TENSE_P_PRESENT) {
// 現在分詞
if(lastVerb->which == NULL) return;
} else {
// 過去分詞
if(IsAlwaysIntransitiveVerb(lastVerb)) return;
}
DisconnectTOKEN(start, lastVerb);
AddChildTOKEN(lastNoun, lastVerb);
if(lastVerb->frTense & (FR_TENSE)(FR_TENSE_PASSIVE | FR_TENSE_P_PAST)) {
SelectJpVerb2_Passive(lastNoun, lastVerb);
lastVerb->jpProp |= JP_PROP_PASSIVE;
// l'amour perdu 失われる恋愛 -> 失われた恋愛
if(lastVerb->jpProp & JP_PROP_ACTION)
lastVerb->frTense = (FR_TENSE)(lastVerb->frTense | FR_TENSE_PASSE);
} else if(lastVerb->frTense == FR_TENSE_P_PRESENT) // 名詞 + 現在分詞ならもう一度、訳を考える(名詞は主格)
SelectJpVerb2_Active(lastNoun, lastVerb);
if(lastVerb->which == NULL)
currentTree->prtControl = PRT_CONTROL_DISABLE;
}
//
// avoirと過去分詞動詞をまとめる
//
void
MakeComposePasse(TOKEN *start, TOKEN *avoir, TOKEN *pp, TOKEN *rien)
{
FR_TENSE tense = avoir->frTense;
JP_PROP savJpProp = (JP_PROP)(avoir->jpProp * ~JP_PROP_ALL);
if(tense & FR_TENSE_ORIGIN) // avoir chante
pp->frTense = FR_TENSE_ORIGIN_C;
else if(tense & FR_TENSE_PRESENT) // j'ai chante
pp->frTense = FR_TENSE_PASSE_C;
else if(tense & FR_TENSE_IMPERFECT) // j'avais chante
pp->frTense = FR_TENSE_PLUS_PERFECT;
else if(tense & FR_TENSE_FUTURE_SIMPLE) // j'aurai chante
pp->frTense = FR_TENSE_FUTURE_ANTERIEUR;
else if(tense & FR_TENSE_CONDITIONAL_PRESENT) // j'aurais chante
pp->frTense = FR_TENSE_CONDITIONAL_PASSE;
else if(tense & FR_TENSE_SUBJUNCTIVE_PRESENT) // j'ait chante
pp->frTense = FR_TENSE_SUBJUNCTIVE_PASSE;
else if(tense & FR_TENSE_SUBJUNCTIVE_IMPERFECT) // j'eusse chante
pp->frTense = FR_TENSE_SUBJUNCTIVE_PASSE;
else
return;
pp->frTense = (FR_TENSE)(pp->frTense & ~FR_TENSE_P_PAST & ~FR_TENSE_PASSIVE);
// 命令形を継続 eg) Ayez achev{ ce travail.
pp->frTense = (FR_TENSE)(pp->frTense | (FR_TENSE)(tense & FR_TENSE_ORDER));
pp->frAttrib = avoir->frAttrib;
pp->punctuation = avoir->punctuation;
pp->jpProp = (JP_PROP)(pp->jpProp | savJpProp);
pp->jpProp = (JP_PROP)(pp->jpProp * ~JP_PROP_PASSIVE);
pp->scoreCombine += SCORE_COMPOSE_C;
TOKEN *adverb = avoir->child; // avoirが既に副詞を持っている可能性もある。 eg) je ne l'ai jamai vu.
if(adverb) {
AddChildTOKEN(pp, adverb);
ImproveJapanese(pp, adverb, pp, JP_PROP_ALL, JP_PROP_ALL);
// 後で、減点の対象とならないように Je suis <souvent> all{ @ Londres.
for(TOKEN *q = adverb; q; q = q->next)
q->scoreCombine -= SCORE_INSERTED_ADVERB;
}
if(IsTokenFrench(avoir, "]tre")
&& avoir->object1
&& (avoir->object1->frPart & FR_PART_ADVERB)) { // 副詞が属詞として処理されてしまった場合 eg) je suis souvent all{ @ Londres.
AddChildTOKEN(pp, avoir->object1);
ImproveJapanese(pp, avoir->object1, pp, JP_PROP_ALL, JP_PROP_ALL);
}
// <avoir>の位置に動詞をまとめる
// le lui avez-vous donne? -> le lui donne-vous?
DisconnectTOKEN(start, pp);
SwapToken(avoir, pp);
if(rien) {
DisconnectTOKEN(start, rien);
InsertTOKEN(avoir, rien);
}
}
//
// 受動態を作る
//
void
CombineEtrePastParticiple(TOKEN *start, TOKEN *etre, TOKEN *pp)
{
pp->frAttrib = etre->frAttrib;
// 否定とか質問とか
pp->jpProp = (JP_PROP)(pp->jpProp | (JP_PROP)(etre->jpProp * ~JP_PROP_ALL));
// 過去形とか
pp->frTense = (FR_TENSE)(pp->frTense | etre->frTense | FR_TENSE_ETRE_PASSIVE);
pp->frTense = (FR_TENSE)(pp->frTense & ~FR_TENSE_PASSIVE);
// <etre>が複合過去だったかもしれない?
pp->scoreCombine += etre->scoreCombine;
// etreに付いていた副詞を保存
if(etre->child)
AddChildTOKEN(pp, etre->child);
DisconnectTOKEN(start, etre);
}
//
// 自動詞を他動詞に変換する
// eg) un devoir @ finir 終わるべき宿題 -> 終わらせるべき宿題
//
void
ChangeIntransitiveVerbToTransitive(TOKEN *noun, TOKEN *prep)
{
TOKEN *verb = NULL;
if(prep == NULL) goto Error;
verb = prep->object1;
if(verb == NULL
|| !(verb->frPart & FR_PART_VERB)) goto Error;
// 元から他動詞
if(verb->object1 || verb->object2) return;
// 他動詞となりえない
if(IsAlwaysIntransitiveVerb(verb) == FALSE) {
TOKEN *null = PutNullNoun();
null->jpProp = noun->jpProp;
null->frAttrib = noun->frAttrib;
InsertTOKEN(verb, null);
verb->which = NULL;
SelectJpVerb1(verb);
if(verb->which == NULL) goto Error;
if(verb->object1 != null && verb->object2 != null)
DisconnectTOKEN(verb, null);
}
return;
Error:
PrintInternalError( "Itnernal Error <ChangeIntransitiveVerbToTransitive>\n");
}
//
// いつも自動詞か(他動詞とならないか)?
//
BOOL
IsAlwaysIntransitiveVerb(TOKEN *verb)
{
if(verb == NULL
|| !(verb->frPart & FR_PART_VERB))
return(FALSE);
JP_VERB const *jpVerb = ((VERB *)verb->what)->jpVerb;
int proposed = ((VERB *)verb->what)->proposed;
while(proposed-- > 0) {
if(jpVerb->frPart1 & FR_PART_NOUN) return(FALSE);
if(jpVerb->frPart2 & FR_PART_NOUN) return(FALSE);
jpVerb++;
}
return(TRUE);
}
//
// 動詞原形を名詞化する。
//
void
ChangeVerbToNoun(TOKEN *start)
{
TOKEN *prev = start;
TOKEN *p = prev;
for(p = start; p; p = p->next) {
if( p->which // すでにObjectが確定していること
&& (p->frPart & FR_PART_VERB)
&& (p->frTense & FR_TENSE_ORIGIN)
&& (p->frPartChoice & FR_PART_NOUN)
&& !IsObjectMatch(prev, FR_PART_VERB_UNCLEAR)) { // 動詞辞書の方で、拾ってもらおう
TOKEN *altP = CopyCurrentTree(p, "ChangeVerbToNoun", FR_PART_NOUN);
FR_PART frPart = (FR_PART)(p->frPart & FR_PART_COMBINE); // <et>が付いていた場合
p->frPart = (FR_PART)(FR_PART_NOUN_VERB | frPart);
isChanged = TRUE;
}
prev = p;
}
}
//
// 過去分詞の形容詞化
//
void
ChangeParticipleToAdjective(TOKEN *start)
{
TOKEN *p;
TOKEN *lastVerb = NULL;
for(p = start; p; p = p->next) {
if(IsObjectMatch(p, FR_PART_VERB_UNCLEAR)
&& (p->frTense & (FR_TENSE)(FR_TENSE_PASSIVE | FR_TENSE_P_PAST))) {
lastVerb = p;
}
}
if(lastVerb == NULL
|| IsAlwaysIntransitiveVerb(lastVerb))
return;
lastVerb->which = NULL;
SelectJpVerb2_Passive(NULL, lastVerb);
lastVerb->jpProp |= JP_PROP_PASSIVE;
// l'amour perdu 失われる恋愛 -> 失われた恋愛
if(lastVerb->jpProp & JP_PROP_ACTION)
lastVerb->frTense = (FR_TENSE)(FR_TENSE_P_PAST | FR_TENSE_PASSE);
}
//
// 文章 + <et> + 文章 -> 文章
//
void
CombineEtVerb(TOKEN *start)
{
TOKEN *p;
TOKEN *lastEt = NULL;
for(p = start; p && p->next; p = p->next) {
if( p->frPart == FR_PART_COMBINE_VERB
&& p->object2 == NULL
&& (p->next->frPart & FR_PART_VERB)
&& p->next->which) {
lastEt = p;
} else if(p->frPart == FR_PART_COMBINE_VERB
&& p->object2 == NULL) {
lastEt = NULL;
}
}
if(lastEt == NULL) return;
TOKEN *verb = lastEt->next;
if(verb->subject == NULL) {
// verb->subject = PutNullNoun();
verb->frPart = (FR_PART)(verb->frPart | FR_PART_SENTENCE_NO_SUBJECT);
}
DisconnectTOKEN(start, verb);
lastEt->object2 = verb;
SelectJpCombine2(lastEt, verb);
}
//
// <所有形容詞> + <動詞> -> <文章>
// eg) @ son arriv{ @ ce village. 彼がその村に着いたら
//
CMP_TOKEN pat_AdjectiveVerb[] = {
CMP_TOKEN( FR_PART_ADJECTIVE_POSSESIVE, JP_PROP_NONE, NULL),
CMP_TOKEN( FR_PART_VERB_P_PAST, JP_PROP_NONE, IsWhichFixed),
CMP_TOKEN( FR_PART_NONE )
};
void
CombineAdjectiveVerb(TOKEN *start)
{
TOKEN *p;
TOKEN *lastAdjective = NULL;
for(p = start; p; p = p->next) {
if(IsPatternMatch(pat_AdjectiveVerb, p)) {
lastAdjective = p;
}
}
if(lastAdjective) {
CombineAdjectiveVerb(start, lastAdjective, lastAdjective->next);
}
}
void
CombineAdjectiveVerb(TOKEN *start, TOKEN *adj, TOKEN *verb)
{
ChangePossesAdjectiveToSubjectNoun(adj);
CombineSubjectVerb(start, adj, verb);
verb->frPart = FR_PART_SENTENCE_PPAST;
// @ son arrive, 彼は到着すると -> 彼が到着すると
adj->jpEmphasis |= JP_EMPHASIS_GA;
}
typedef struct {
char *adjective;
char *noun;
} ADJ2NOUN;
ADJ2NOUN AdjectiveSubjectTable[] = {
{ "mon", "je"},
{ "ma", "je"},
{ "mes", "je"},
{ "ton", "te"},
{ "ta", "te"},
{ "tes", "te"},
{ "son", "il"},
{ "sa", "il"},
{ "ses", "il"},
{ "votre", "vous" },
{ "vos", "vous" },
{ "notre", "nous" },
{ "nos", "nous" },
{ "leur", "ils" },
{ "leurs", "ils" },
{ "", "" } // End Code
};
void
ChangePossesAdjectiveToSubjectNoun(TOKEN *p)
{
ADJ2NOUN *dic = AdjectiveSubjectTable;
while(dic->adjective[0]) {
if(IsTokenFrench(p, dic->adjective)) {
ChangeToPronoun(p, dic->noun);
return;
}
dic++;
}
PrintInternalError( "Internal Error <ChangePossesAdjectiveToSubjectNoun>");
}